//----------------------------------------------------------------------------------------------
//	Filename:	PointCloud.cpp
//	Author:		Sandro Spina
//	Date:		31/07/2012
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
#include "Shape/PointCloud.h"

using namespace Illumina::Core;
//----------------------------------------------------------------------------------------------
IPointCloud::IPointCloud(void) 
	: IShape() 
{ }
//----------------------------------------------------------------------------------------------
IPointCloud::IPointCloud(const std::string &p_strName) 
	: IShape(p_strName) 
{ }
//----------------------------------------------------------------------------------------------
int IPointCloud::MaterialGroupIds=0;

int IPointCloud::NumberOfMaterials=28;

int IPointCloud::GetNumberOfMaterials()
{
	return IPointCloud::NumberOfMaterials;
}

void IPointCloud::ResetMaterialsIds()
{
	IPointCloud::MaterialGroupIds = -1;
}
//----------------------------------------------------------------------------------------------
int IPointCloud::GetNextMaterialId()
{
	IPointCloud::MaterialGroupIds+=1;
	IPointCloud::MaterialGroupIds = IPointCloud::MaterialGroupIds % NumberOfMaterials;
	return IPointCloud::MaterialGroupIds;
}
//----------------------------------------------------------------------------------------------
bool IPointCloud::IsBounded(void) const {
	return false;
}
//----------------------------------------------------------------------------------------------
void IPointCloud::ComputeBoundingVolume(void)
{
	m_boundingBox.Invalidate();
	if (m_pointList.size() > 0) {
		VertexP pVertex;
		for (int nIdx = 0, count = (int)m_pointList.size(); nIdx < count; nIdx++)
		{
			pVertex = m_pointList[nIdx].m_vertex;
			m_boundingBox.Union(pVertex.Position);
		}
	}
	m_boundingBox.SetMinExtent(m_boundingBox.GetMinExtent() - Vector3(m_fSphereRadius));
	m_boundingBox.SetMaxExtent(m_boundingBox.GetMaxExtent() + Vector3(m_fSphereRadius));
}
//----------------------------------------------------------------------------------------------
IBoundingVolume* IPointCloud::GetBoundingVolume(void) const {
	return (IBoundingVolume*)&m_boundingBox;
}
//----------------------------------------------------------------------------------------------
int IPointCloud::GetSize()
{
	return m_pointList.size();
}
//----------------------------------------------------------------------------------------------
size_t IPointCloud::AddPoint(const CloudPoint &p_vertex)
{
	m_pointList.push_back(p_vertex);
	return m_pointList.size() - 1;
}
//----------------------------------------------------------------------------------------------
void IPointCloud::AddPointList(const CloudPoint *p_pVertex, int p_nCount)
{
	for (int idx = 0; idx < p_nCount; idx++, p_pVertex++)
		AddPoint(*p_pVertex);
}
//----------------------------------------------------------------------------------------------
void IPointCloud::AddPointList(const List<CloudPoint> &p_vertexList)
{
	for (int idx = 0; idx < p_vertexList.Size(); idx++)
		AddPoint(p_vertexList[idx]);
}
//----------------------------------------------------------------------------------------------
bool IPointCloud::UpdateNormals(void)
{
	// Check for normal semantic before applying normal update
	if ((Vertex::GetDescriptor() & VertexFormat::Normal) > 0)
	{
		Vector3 vec3Normal;		
		int nVertexCount = m_pointList.size();
		return true;
	}

	return false;
}
//----------------------------------------------------------------------------------------------
float IPointCloud::GetArea(void) const {
	return m_fArea;
}
//----------------------------------------------------------------------------------------------
float IPointCloud::GetPdf(const Vector3 &p_point) const {
	return 1.0f / m_fArea;
}
//----------------------------------------------------------------------------------------------
Vector3 IPointCloud::SamplePoint(float p_u, float p_v, Vector3 &p_normal) 
{
	//int triangleToSample = Maths::Min(TriangleList.Size() * m_random.NextFloat(), TriangleList.Size() - 1);
	//return TriangleList[triangleToSample].SamplePoint(p_u, p_v, p_normal);
	return Vector3::Zero;
}
//----------------------------------------------------------------------------------------------
Vector3 IPointCloud::SamplePoint(const Vector3 &p_viewPoint, float p_u, float p_v, Vector3 &p_normal) 
{
	//Vector3 samplePoint;

	//samplePoint = SamplePoint(p_u, p_v, p_normal);

	//float cosTheta = Vector3::Dot((samplePoint - p_viewPoint), p_normal);

	//if (cosTheta > 0)
	//	p_normal = -p_normal;

	//return samplePoint;
	return Vector3::Zero;
}
//----------------------------------------------------------------------------------------------
void IPointCloud::ComputeArea(void)
{
	m_fArea = 0;	
}
//----------------------------------------------------------------------------------------------